﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Red.GameData.Raw
{
    /// <summary>
    ///  Collection representing ALL of the objects loaded in the system, each object is independent until resolved.
    /// </summary>
    public partial class DataCollection
    {
        /// <summary>
        /// Absolute path to the root directory of the whole data collection
        /// </summary>
        public string RootPath { get; private set; }

        /// <summary>
        /// All known physical files that were loaded into this collection
        /// </summary>
        public List<DataFile> AllFiles { get; private set; }

        /// <summary>
        /// Flat list of all objects in the system, potentially HUGHe, use with care
        /// </summary>
        public List<DataObject> AllObjects { get; private set; }

        /// <summary>
        /// Initialize data collection
        /// </summary>
        /// <param name="rootPath">Root path for the whole collection (eventuall all files are under some common root)</param>
        internal DataCollection(string rootPath)
        {
            RootPath = rootPath;
            AllFiles = new List<DataFile>();
            AllObjects = new List<DataObject>();

            _objectMap = new Dictionary<Guid, DataObject>();
            _unassignedObjects = new DataFile(this, "<unassigned>");
        }

        /// <summary>
        /// Returns list of object that were modified
        /// </summary>
        public List<DataObject> ModifiedObjects
        {
            get
            {
                List<DataObject> ret = new List<DataObject>();
                foreach (var obj in AllObjects)
                {
                    if (obj.IsModified)
                    {
                        ret.Add(obj);
                    }
                }

                return ret;
            }
        }

        /// <summary>
        /// Returns a list of files that contain modified objects
        /// NOTE: the list also contains the so called "unassigned" file representing object that don't yet have a file
        /// </summary>
        public List<DataFile> ModifiedFiles
        {
            get
            {
                List<DataFile> ret = new List<DataFile>();
                foreach (var obj in AllFiles)
                {
                    if (obj.IsModified)
                    {
                        ret.Add(obj);
                    }
                }

                return ret;
            }
        }

        /// <summary>
        /// Gets the objects that are NOT assigned to any file
        /// We need to take care of those object BEFORE it's possible to save stuff successfully
        /// Such file-less objects are created usually when adding totally fresh new content that has no context (and therefore cannot be pre-assigned to existing files)
        /// </summary>
        public List<DataObject> UnassignedObjects
        {
            get
            {
                return _unassignedObjects.ObjectsInFile;
            }
        }

        /// <summary>
        /// Finds a very specific object by it's GUID. This is a primary binding site for the whole system.
        /// Internally it uses a simple dictionary to get along.
        /// </summary>
        /// <param name="id">Well, the GUID of the object you want to find</param>
        /// <returns></returns>
        public DataObject Find(Guid id)
        {
            if (id == Guid.Empty)
                return null;

            DataObject ret = null;
            _objectMap.TryGetValue(id, out ret);
            return ret;
        }

      

        /// <summary>
        /// Map of all objects known in the system
        /// </summary>
        private Dictionary<Guid, DataObject> _objectMap;

        /// <summary>
        /// Objects that are not assigned to files yet, they will have to be moved to existing (or new) files before we can save
        /// </summary>
        private DataFile _unassignedObjects; 
    }

}
